﻿using System;
using System.Globalization;
using System.IO;
using System.Runtime.InteropServices.ComTypes;
using System.Text;
using System.Text.RegularExpressions;
using System.Xml;
using System.Xml.Serialization;

namespace Isaac.Joy.Serialize
{
    public static class XmlSerializable
    {
        /// <summary>
        /// 对象序列化为xml字符串
        /// </summary>
        /// <param name="value">被序列化的对象</param>
        /// <param name="type">被序列化的类型</param>
        /// <returns></returns>
        public static string Serialize(Object value, Type type)
        {
            var sb = new StringBuilder();
            var writer = new StringWriter(sb, CultureInfo.CurrentCulture);

            var serializer = new XmlSerializer(type);
            serializer.Serialize(writer, value);
            return sb.ToString().Replace("utf-16", "utf-8");
        }

        /// <summary>
        /// 对象序列化为xml字符串
        /// </summary>
        /// <typeparam name="T">对象类型</typeparam>
        /// <param name="value">被序列化的对象</param>
        /// <returns></returns>
        public static string Serialize<T>(Object value)
        {
            return Serialize(value, typeof(T));
        }

        /// <summary>
        /// 对象序列化为xml字符串
        /// </summary>
        /// <param name="value">被序列化的对象</param>
        /// <returns></returns>
        public static string Serialize(Object value)
        {
            return Serialize(value, value.GetType());
        }

        /// <summary>
        /// 对象反序列化
        /// </summary>
        /// <param name="type">对象类型</param>
        /// <param name="xml">xml字符串</param>
        /// <returns></returns>
        public static object Deserialize(String xml, Type type)
        {
            var reader = XmlReader.Create(new StringReader(xml));
            var serializer = new XmlSerializer(type);
            return serializer.Deserialize(reader);
        }

        /// <summary>
        /// 对象反序列化
        /// </summary>
        /// <typeparam name="T">对象类型</typeparam>
        /// <param name="xml">xml字符串</param>
        /// <returns></returns>
        public static T Deserialize<T>(String xml)
        {
            return (T)Deserialize(xml, typeof(T));
        }

        /// <summary>
        /// 对象反序列化
        /// </summary>
        /// <param name="node">对象类型</param>
        /// <param name="type">xml节点</param>
        /// <returns></returns>
        public static object Deserialize(XmlNode node, Type type)
        {
            var sbXml = new StringBuilder();
            sbXml.AppendLine("<?xml version=\"1.0\" encoding=\"utf-8\" ?>");
            sbXml.AppendLine(Regex.Replace(node.OuterXml, "xmlns=\"[\\S\\s]*?\"", ""));

            return Deserialize(sbXml.ToString(), type);
        }

        /// <summary>
        /// 对象反序列化
        /// </summary>
        /// <typeparam name="T">对象类型</typeparam>
        /// <param name="node">xml节点对象</param>
        /// <returns></returns>
        public static T Deserialize<T>(XmlNode node)
        {
            return (T)Deserialize(node, typeof(T));
        }

        /// <summary>
        /// 从xml文件中加载对象
        /// </summary>
        /// <param name="filePath">文件地址</param>
        /// <param name="type">对象类型</param>
        /// <returns></returns>
        public static object LoadFromXml(string filePath, Type type)
        {
            if (!File.Exists(filePath)) return null;

            using (var reader = new StreamReader(filePath))
            {
                var xmlSerializer = new XmlSerializer(type);
                return xmlSerializer.Deserialize(reader);
            }
        }

        /// <summary>
        /// 从xml文件中加载对象
        /// </summary>
        /// <typeparam name="T">对象类型</typeparam>
        /// <param name="filePath">文件地址</param>
        /// <returns></returns>
        public static T LoadFromXml<T>(string filePath)
        {
            return (T)LoadFromXml(filePath, typeof(T));
        }

        /// <summary>
        /// 序列化并保存为文件
        /// </summary>
        /// <param name="value">对象值</param>
        /// <param name="filePath">文件地址</param>
        public static void SaveXml(Object value, string filePath)
        {
            using (var stream = new FileStream(filePath, FileMode.Create, FileAccess.Write, FileShare.ReadWrite))
            {
                var serializer = new XmlSerializer(value.GetType());
                serializer.Serialize(stream, value);
            }
        }
    }
}
